const express = require('express')
const router = express.Router()
// jwt
const jwt = require('jsonwebtoken')
// 导入密钥
const config = require('../secert')
// 上传图片需要
const fs = require('fs')
const multer = require('multer')
// 参数校验
const { check, body, validationResult } = require('express-validator')
// 日期转换
const moment = require('moment')

// mongoose模块
// 用户表
const UserModel = require('../model/UserModel')
// 好友表
const FriendModel = require('../model/FriendModel')
// 私聊表
const PrivateChatModel = require('../model/PrivateChatModel')
// 群（信息）表
const GroupModel = require('../model/GroupModel')
// 群成员表
const GroupUserModel = require('../model/GroupUserModel')
// 群消息表
const GroupChatModel = require('../model/GroupChatModel')
// 空间动态表
const SpaceModel = require('../model/SpaceModel')


// 引入工具函数
const utils = require('../utils/index')

// 测试接口
router.get('/', (req, res) => {
    res.send('服务器启动成功')
})

/** ===================================== 登录注册接口 =========================================== */
/**
 * 登录接口
 * @method post
 */
router.post('/login',async (req, res) => {
    const {phone, password} = req.body
    try {
        // 在数据库中查找用户
        const user = await UserModel.findOne({ phone })
        if (!user) {
            return res.json({
                status: 400,
                msg: '该用户不存在'
            })
        }
        // 验证密码是否正确
        const pwd = await UserModel.findOne({ password })
        if (!pwd) {
            return res.json({
                status: 401,
                msg: '密码错误'
            })
        }
        // 如果用户名和密码都正确，则返回用户信息
        res.json({
            status: 200,
            msg: '登录成功',
            data: {
                token: user.token,
                _id: user._id,
                nick: user.nick,
                imgUrl: user.imgUrl
            }
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '登录失败'
        })
    }
})

/**
 * 注册接口
 * @method post
 */
router.post('/register', [
    // 参数校验
    // 手机号
    check('phone', '手机号不合法').isLength({ min: 11, max: 11 }),
    check('phone', '手机号不能为空').notEmpty(),
    // 密码
    check('password', '密码不能为空').notEmpty(),
    // 昵称
    check('nick', '昵称不能为空').notEmpty(),
    check('nick', '昵称最大不能超过15个字').isLength({ max: 15 }),
    // 性别
    check('sex', '性别不能为空').notEmpty(),
    check('sex').isIn(['男', '女']).withMessage('性别必须为男或女'),
    // 生日
    check('birthday', '日期不能为空').notEmpty(),
    body('birthday').custom(value => {
        const convertedDate = moment(value, 'YYYY-M-D', true)
        if (convertedDate.isValid()) {
            return true
        }
        throw new Error('请填写正确日期')
    }),
    // 签名
    check('sign', '个性签名不能为空').notEmpty(),
    check('sign', '个性签名最大不能超过50个字').isLength({ max: 50 }),
], async (req, res) => {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
        return res.json({
            status: 405,
            msg: '参数错误',
            data: errors.array()
        })
    }
    let { phone, password, nick, sex, birthday, sign } = req.body
    // 获取WaiFCode码
    let WaiFCode = 'WaiFCode_' + phone
    // 计算年龄
    let age = utils.calculateAge(birthday)
    // 计算星座
    let start = utils.getStart(birthday)
    try {
        // 在数据库中查找用户
        const user = await UserModel.findOne({ phone })
        if (user) {
            return res.json({
                status: 400,
                msg: '该用户已注册'
            })
        }
        await UserModel.create({
            phone, // 手机号
            WaiFCode: 'WaiFCode_' + phone, // WaiF号
            password, // 密码
            nick, // 昵称
            imgUrl: sex === '男' ? '/user_pic1.jpeg' : '/user_pic2.jpeg', // 头像
            sex, // 性别 
            age, // 年龄
            birthday, // 生日
            start, // 星座
            sign, // 个性签名
            token: jwt.sign({ 
                phone,
                WaiFCode
            }, config.jwtSecret, {
                expiresIn: 60 * 1
            })
        })
        res.json({
            status: 200,
            msg: '注册成功'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '注册失败'
        })
    }
})

/** ===================================== 用户主页信息接口 ======================================= */
/**
 * userhome主页信息
 */
router.get('/home/user',async (req, res) => {
    // _id：自己的id  urlId：浏览器路径的id
    let { _id, urlId } = req.query
    try {
        const user = await UserModel.findOne({ _id: urlId }, { token: 0, password: 0 })
        const friendState = await FriendModel.findOne({ 
            userId: _id,
            friendId: urlId
        }, { state: 1 })
        if (_id === urlId) {
            return res.json({
                status: 200,
                data: {
                    user,
                    friendState: 3 // 用户是自己（3为编辑资料）
                }
            })
        } else if (!friendState) {
            return res.json({
                status: 200,
                data: {
                    user
                }
            })
        }
        res.json({
            status: 200,
            data: {
                user,
                friendState: friendState.state
            }
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '加载失败'
        })
    }
})

/**
 * message列表页顶部用户头像和昵称
 */
router.get('/tabbar/message/userinfo',async (req, res) => {
    let _id = req.query._id
    try {
        let info = await UserModel.findOne({_id}, {nick: 1, imgUrl: 1})
        res.json({
            status: 200,
            data: info
        })
    } catch (error) {
        res.json({
            status: 404,
            data: '服务器错误'
        })
    }  
})

/**
 * 上传图片  post请求
 * 说明：
 * 1、后台安装multer模块，引入fs模块
 * 2、router.js入口文件导入模块
 *      const fs = require('fs')
 *      const multer = require('multer')
 * 3、post请求需要引入urlencoded
 */
var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./upload/user")
    },
    filename: function (req, file, cb) {
        cb(null, Date.now() + "-" + file.originalname)
    }
})
var createFolder = function (folder) {
    try {
        fs.accessSync(folder)
    } catch (e) {
        fs.mkdirSync(folder)
    }
}
var uploadFolderUser = './upload/user'
createFolder(uploadFolderUser)
var upload = multer({ storage: storage })
router.post('/upload/user', upload.single('file'), async (req, res, next) => {
    var file = req.file
    let _id = req.query._id
    /**
     * file:
     * {
        fieldname: 'file',
        originalname: 'no_friendOrgroup.png',
        encoding: '7bit',
        mimetype: 'image/png',
        destination: './upload/user',
        filename: '1683732830725-no_friendOrgroup.png',
        path: 'upload/user/1683732830725-no_friendOrgroup.png',
        size: 89253
        }
     */
    // console.log('文件类型：%s', file.mimetype)
    // console.log('原始文件名：%s', file.originalname)
    // console.log('文件大小：%s', file.size)
    // console.log('文件保存路径：%s', file.path)
    try {
        res.json({ res_code: '0', name: file.originalname, url: `/${file.filename}` })
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 更新用户信息接口
 * @method post
 */
router.post('/update/user',  [
    // 参数校验
    // id
    check('_id', '_id参数不能为空').notEmpty(),
    // 昵称
    check('nick', '昵称不能为空').notEmpty(),
    check('nick', '昵称不最大不能超过15个字').isLength({ max: 15 }),
    // 性别
    check('sex', '性别不能为空').notEmpty(),
    check('sex').isIn(['男', '女']).withMessage('性别必须为男或女'),
    // 生日
    check('birthday', '日期不能为空').notEmpty(),
    body('birthday').custom(value => {
        const convertedDate = moment(value, 'YYYY-M-D', true)
        if (convertedDate.isValid()) {
            return true
        }
        throw new Error('请填写正确日期')
    }),
    // 签名
    check('sign', '个性签名不能为空').notEmpty(),
    check('sign', '个性签名最大不能超过50个字').isLength({ max: 50 }),
], async (req, res) => {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
        return res.json({
            status: 405,
            msg: '参数错误',
            data: errors.array()
        })
    }
    const { _id, nick, sex, birthday, sign, imgUrl } = req.body
    // 计算年龄
    let age = utils.calculateAge(birthday)
    // 计算星座
    let start = utils.getStart(birthday)
    try {
        await UserModel.updateOne({_id}, { nick, sex, birthday, sign, age, start, imgUrl })
        res.json({
            status: 200,
            msg: '保存成功'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '保存失败'
        })
    }
})

/** ======================================= 搜索好友/群接口 ========================================= */
router.get('/search',async (req, res) => {
    let keyword = req.query.keyword
    try {
        // 用户搜索
        let friends = await UserModel.find({ nick: { $regex: keyword } }, { nick: 1, imgUrl: 1, sign: 1 })
        // 群搜索
        let groups = await GroupModel.find({ groupName: { $regex: keyword } }, { groupName: 1, imgUrl: 1 })
        if (!friends.length && !groups.length) {
            return res.json({
                status: 400,
                msg: '暂无数据',
                result: false
            })
        }
        res.json({
            status: 200,
            data: {
                friendList: friends,
                groupList: groups
            }
        })
    } catch (error) {
        res.json({
            status: 404,
            result: false
        })
    }
})

/** ========================================== 好友接口 =========================================== */
/**
 * 发送好友申请
 * userId 自己的id
 * friendId 好友id
 */
router.post('/friend/add', [
    // 参数校验
    check('userId', 'userId参数不能为空').notEmpty(),
    check('friendId', 'friendId参数不能为空').notEmpty(),
], async (req, res) => {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
        return res.json({
            status: 405,
            msg: '参数错误',
            data: errors.array()
        })
    }
    const { userId, friendId } = req.body
    try {
        let result = await FriendModel.create([
            // 好友表自己插入对方（申请方，state => 0）
            { userId, friendId, state: 0 },
            // 好友表对方插入自己（接收方，state => 4）
            {
                userId: friendId,
                friendId: userId,
                state: 4
            }
        ])
        res.json({
            status: 200,
            msg: '申请中'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '申请失败，请重试'
        })
    }
})

/**
 * 联系人页面展示好友列表（只返回好友状态state为1的 => 已为好友）
 */
router.get('/contacts/friend',async (req, res) => {
    const userId = req.query.userId
    try {
        let friendList = await FriendModel.find({userId, state: 1}).populate('friendId', ['nick', 'sign', 'imgUrl'])
        res.json({
            status: 200,
            data: friendList
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '请求失败'
        })
    }
})

/**
 * 删除好友
 */
router.get('/del/friend', async (req, res) => {
    const { userId, friendId } = req.query
    try {
        await FriendModel.deleteOne({userId, friendId})
        await FriendModel.deleteOne({userId: friendId, friendId: userId})
        res.json({
            status: 200,
            msg: '删除成功'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '删除失败'
        })
    }
})

/**
 * 获取到当前未同意的好友申请列表
 */
router.get('/get/friend/noagree', async (req, res) => {
    const { userId }  = req.query
    try {
        let friendApply = await FriendModel.find({userId, state: 4}).sort({_id: -1}).populate('friendId', ['imgUrl', 'nick'])
        res.json({
            status: 200,
            data: friendApply
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 同意好友申请
 */
router.post('/friend/agree', [
    // 参数校验
    check('userId', 'userId参数不能为空').notEmpty(),
    check('friendId', 'friendId参数不能为空').notEmpty(),
], async (req, res) => {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
        return res.json({
            status: 405,
            msg: '参数错误',
            data: errors.array()
        })
    }
    const { userId, friendId } = req.body
    try {
        await FriendModel.updateOne({userId, friendId}, {state: 1})
        await FriendModel.updateOne({userId: friendId, friendId: userId}, {state: 1})
        res.json({
            status: 200,
            msg: '添加成功'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '添加失败'
        })
    }
})

/** ========================================== 群接口 ============================================ */
/**
 * 新建群聊接口
 * imgUrl: 前端已经把地址写好，只用存数据库就行，群头像图片上传接口只用把头像存入 /upload/group 中就行
 */
router.post('/create/group', [
    // 参数校验
    // 群主id
    check('userId', 'userId参数不能为空').notEmpty(),
    // 群名
    check('groupName', '群名不能为空').notEmpty(),
    check('groupName', '群名最大不能超过15个字').isLength({ max: 15 }),
    // 群简介
    check('sign', '群名不能为空').notEmpty(),
    check('sign', '群名最大不能超过50个字').isLength({ max: 50 }),
], async (req, res) => {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
        return res.json({
            status: 405,
            msg: '参数错误',
            data: errors.array()
        })
    }
    const { userId, groupName, sign, imgUrl } = req.body
    try {
        let group = await GroupModel.create({
            userId,
            groupName,
            groupNumber: Date.parse(new Date()) + utils.getRandom(100, 999),
            sign,
            imgUrl,
            creatTime: utils.getNowTime()
        })
        let groupUser = await GroupUserModel.create({
            groupId: group._id,
            userId: group.userId,
            state: 1
        })
        res.json({
            status: 200,
            msg: '创建成功'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '创建失败'
        })
    }
})

/**
 * 群头像上传
 */
var storageGroup = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./upload/group")
    },
    filename: function (req, file, cb) {
        cb(null, Date.now() + "-" + file.originalname)
    }
})
var createFolder = function (folder) {
    try {
        fs.accessSync(folder)
    } catch (e) {
        fs.mkdirSync(folder)
    }
}
var uploadFolderGroup = './upload/group'
createFolder(uploadFolderGroup)
var uploadGroup = multer({ storage: storageGroup })
router.post('/upload/group', uploadGroup.single('file'), async (req, res, next) => {
    var file = req.file
    res.json({ res_code: '0', name: file.originalname, url: `/${file.filename}` })
})

/**
 * 获取群主页信息
 */
router.get('/home/group',async (req, res) => {
    const { groupId, userId } = req.query
    // 查看当前群是否有该用户：1、群id 2、当前用户id 3、拿到当前用户id去群的群成员表中查找
    try {
        let group = await GroupModel.findOne({_id: groupId})
        // 查看当前用户是否加入该群（0:申请中，1:已为加入该群，2:未加入群）
        let userState = await GroupUserModel.findOne({groupId, userId}, {state: 1})
        if (!userState) {
            // 在群成员中未找到当前用户（未加入该群）
            return res.json({
                status: 200,
                data: group,
                state: 2
            })
        } else if (userState.state === 1) {
            // 已经加入该群
            return res.json({
                status: 200,
                data: group,
                state: 1
            })
        } else {
            // 申请中
            res.json({
                status: 200,
                data: group,
                state: 0
            })
        }
    } catch (error) {
        res.json({
            status: 404,
            data: '服务器错误'
        })
    }
})

/**
 * 获取群成员接口
 */
router.get('/get/groupUser',async (req, res) => {
    const { groupId } = req.query
    try {
        let groupUser = await GroupUserModel.find({groupId, state: 1}).populate('userId', ['nick', 'imgUrl'])
        res.json({
            status: 200,
            data: groupUser
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 加入群聊（发送入群申请）
 */
router.post('/group/add', [
    // 参数校验
    check('groupId', 'groupId参数不能为空').notEmpty(),
    check('userId', 'userId参数不能为空').notEmpty(),
], async (req, res) => {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
        return res.json({
            status: 405,
            msg: '参数错误',
            data: errors.array()
        })
    }
    const { groupId, userId } = req.body
    try {
        let addGroup = await GroupUserModel.create({
            groupId,
            userId,
            state: 0
        })
        res.json({
            status: 200,
            msg: '已发送'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '申请失败'
        })
    }
})

/**
 * 联系人页面展示群列表（只返回群状态state为1的 => 已入群）
 */
router.get('/contacts/group',async (req, res) => {
    const userId = req.query.userId
    try {
        let groupList = await GroupUserModel.find({userId, state: 1}).populate('groupId', ['groupName', 'imgUrl'])
        res.json({
            status: 200,
            data: groupList
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '请求失败'
        })
    }
})

/**
 * 获取当前需要修改的群信息
 */
router.get('/get/update/group',async (req, res) => {
    // groupId群id, groupLeaderId群主id
    const { groupId, groupLeaderId } = req.query
    try {
        let groupInfo = await GroupModel.findOne({_id: groupId}, {groupName: 1, sign: 1, imgUrl: 1})
        let groupUserList = await GroupUserModel.find({groupId, state: 1}).find({userId: {$ne: groupLeaderId}}).populate('userId', ['nick', 'imgUrl'])
        res.json({
            status: 200,
            data: {
                groupInfo,
                groupUserList
            }
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 修改群聊信息
 */
router.post('/update/groupInfo', [
    // 参数校验
    // id
    check('_id', '_id参数不能为空').notEmpty(),
    // 群名
    check('groupName', '群名不能为空').notEmpty(),
    check('groupName', '群名最大不能超过15个字').isLength({ max: 15 }),
    // 群简介
    check('sign', '群名不能为空').notEmpty(),
    check('sign', '群名最大不能超过50个字').isLength({ max: 50 }),
], async (req, res) => {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
        return res.json({
            status: 405,
            msg: '参数错误',
            data: errors.array()
        })
    }
    const { _id, groupName, sign, imgUrl } = req.body
    try {
        await GroupModel.updateOne({_id}, {groupName, sign, imgUrl})
        res.json({
            status: 200,
            msg: '修改成功'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '修改失败'
        })
    }
})

/**
 * 删除群成员/群成员退群
 */
router.get('/del/groupUser', async (req, res) => {
    const { userId, groupId } = req.query
    try {
        await GroupUserModel.deleteOne({userId, groupId})
        res.json({
            status: 200,
            msg: '移除成功'
        })
    } catch (error) {
        res.json({
            status: 200,
            msg: '移除失败'
        })
    }
})

/**
 * 退出群聊（分为群主退群和群成员退群）
 * 1、群主退群（解散该群）
 * 2、群成员退群（删除该成员） => 用上面的 /del/groupUser 这个接口
 */
router.get('/del/group', async (req, res) => {
    const { groupId } = req.query
    try {
        // 删除群成员
        await GroupUserModel.deleteMany({groupId})
        // 删除群
        await GroupModel.deleteOne({_id: groupId})
        res.json({
            status: 200,
            msg: 'success'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: 'error'
        })
    }
})

/**
 * 获取群申请通知列表
 */
router.get('/get/group/noagree', async (req, res) => {
    const { userId } = req.query
    try {
        let groupArr = await GroupModel.find({userId})
        let groupIds = groupArr.map(i => i._id)
        let list = []
        for (let i of groupIds) {
            // i => 群id
            let noAgree = await GroupUserModel.find({groupId: i, state: 0}, {state: 0}).sort({_id: -1}).populate('groupId', ['groupName']).populate('userId', ['imgUrl', 'nick'])
            if (noAgree.length > 0) {
                noAgree.forEach(item => {
                    list.push(item)
                })
            }
        }
        res.json({
            status: 200,
            data: list
        })
    } catch (error) {
        res.json({
            status: 404,
            data: '服务器错误'
        })
    }
})

/**
 * 同意入群申请接口
 */
router.post('/group/agree',[
    // 参数校验
    check('userId', 'userId参数不能为空').notEmpty(),
    check('groupId', 'groupId参数不能为空').notEmpty(),
], async (req, res) => {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
        return res.json({
            status: 405,
            msg: '参数错误',
            data: errors.array()
        })
    }
    const { userId, groupId } = req.body
    try {
        await GroupUserModel.updateOne({userId, groupId}, {state: 1})
        res.json({
            status: 200,
            msg: '添加成功'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '添加失败'
        })
    }
})

/** ========================================== 空间接口 =========================================== */
/**
 * 空间动态图片上传接口
 */
var storageSpace = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./upload/space")
    },
    filename: function (req, file, cb) {
        cb(null, Date.now() + "-" + file.originalname)
    }
})
var createFolder = function (folder) {
    try {
        fs.accessSync(folder)
    } catch (e) {
        fs.mkdirSync(folder)
    }
}
var uploadFolderSpace = './upload/space'
createFolder(uploadFolderSpace)
var uploadSpace = multer({ storage: storageSpace })
// photos是跟前端的字段要一致
/**
 *  let form = new FormData()
    form.append('photos', file.file)
 */
// 多图片上传接口
router.post('/space/upload/photos', uploadSpace.array('photos', 9), function (req, res, next) {
    // multer实例.array(fielname[,maxCount])——接收一个以fielname命名的文件数组;maxCount——限制上传的最大数量，这些文件的信息保存在req.files里面
    let files = req.files
    let filesRes = []
    files.forEach(i => {
        filesRes.push(`/${i.filename}`)
    })
    if (files.length === 0) {
        return res.json({ res_code: 500, msg: 'error' })
    } else {
        res.json({ res_code: 200, url: filesRes })
    }
})
// 单图片上传接口
router.post('/space/upload/photo', uploadGroup.single('photo'), async (req, res, next) => {
    var file = req.file
    res.json({ res_code: 200, name: file.originalname, url: `/${file.filename}` })
})

/**
 * 空间动态说说信息上传
 */
router.post('/space/add',[
    check('userId', 'userId参数不能为空').notEmpty(),
    check('textDesc', '文字内容最大不能超过200个字').isLength({ max: 200 }),
], async (req, res) => {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
        return res.json({
            status: 405,
            msg: '参数错误',
            data: errors.array()
        })
    }
    const { userId, textDesc, photos } = req.body
    try {
        await SpaceModel.create({
            userId,
            textDesc,
            photos,
            time: utils.getNowSpecTime()
        })
        res.json({
            status: 200,
            msg: '发布成功'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '发布失败'
        })
    }
})

/**
 * 获取空间动态列表(自己和好友的)
 */
router.get('/space/get',async (req, res) => {
    const { userId } = req.query
    try {
        // 找出当前用户的好友（要通过了申请的好友才行）
        const friends = await FriendModel.find({ userId, state: 1 }).populate('friendId')
        // 获取好友的用户id列表
        const friendIds = friends.map(friend => friend.friendId._id)
        // 获取当前用户
        const nowUser = await UserModel.find({_id:userId})
        // 获取当前用户的id信息
        const nowUserId = nowUser.map(user => user._id)
        let arr = []
        friendIds.forEach(i => { arr.push(i) })
        nowUserId.forEach(i => { arr.push(i) })
        const spaces = await SpaceModel.aggregate([
            // $match：用于筛选出好友的朋友圈信息。
            { $match: { userId: { $in: arr } } },
            // $sort：按照发布时间排序。
            { $sort: { _id: -1 } },
            // $lookup：关联 User 模型，获取用户信息。
            { $lookup: { from: 'users', localField: 'userId', foreignField: '_id', as: 'userId' } },
            // $unwind：展开用户信息。
            { $unwind: '$userId' },
            // $project：只保留需要的字段。
            { $project: { _id: 1, textDesc: 1, photos: 1, time: 1, userId:  { _id: 1, nick: 1, imgUrl: 1 } } }
        ])
        res.json({
            status: 200,
            data: spaces
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 删除动态接口
 */
router.get('/space/del',async (req, res) => {
    const { _id } = req.query
    try {
        await SpaceModel.deleteOne({_id})
        res.json({
            status: 200,
            msg: '删除成功'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '删除失败'
        })
    }
})

/**
 * 用户空间详情接口
 */
router.get('/space/details',async (req, res) => {
    const { userId } = req.query
    try {
        let spaces = await SpaceModel.find({userId}).sort({_id: -1}).populate('userId', ['nick', 'imgUrl'])
        let user = await UserModel.findOne({_id: userId}, {nick: 1, WaiFCode: 1, imgUrl: 1})
        res.json({
            status: 200,
            data: {
                spaces,
                user
            }
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: 'error'
        })
    }
})

/** ========================================== 聊天接口 =========================================== */
/**
 * 获取当前聊天好友的信息
 */
router.get('/message/friend',async (req, res) => {
    // pageSize每页显示的记录数  pageNum当前页码，从1开始
    const { userId, friendId, pageNum } = req.query
    const pageSize = 15
    try {
        let messageList = await PrivateChatModel.find({ $or: [{ userId: userId, friendId: friendId }, { userId: friendId, friendId: userId }] }).populate('userId', ['nick', 'imgUrl']).populate('friendId', ['nick', 'imgUrl']).sort({_id: -1}).skip((pageNum - 1) * pageSize).limit(pageSize)
        let friendNick = await UserModel.findOne({_id: friendId}, { nick: 1 })
        // 判断两人是否为好友
        let isFriend = await FriendModel.find({
            $and: [
                { userId: userId },
                { friendId: friendId },
                { state: { $eq: 1 } }
            ]
        })
        if (isFriend.length === 0) {
            return res.json({
                status: 202,
                data: friendNick,
                msg: '您与ta还不是好友哦'
            })
        }
        if (messageList.length > 0) {
            res.json({
                status: 200,
                data: {
                    friendNick,
                    messageList: messageList.reverse()
                }
            })
        } else {
            res.json({
                status: 201,
                data: friendNick,
                msg: '暂无更多'
            })
        }
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 获取当前聊天群聊的信息
 */
router.get('/message/group',async (req, res) => {
    // pageSize每页显示的记录数  pageNum当前页码，从1开始
    const { userId, groupId, pageNum } = req.query
    const pageSize = 15
    try {
        let messageList = await GroupChatModel.find({ groupId }).populate('userId', ['nick', 'imgUrl']).sort({_id: -1}).skip((pageNum - 1) * pageSize).limit(pageSize)
        let groupNick = await GroupModel.findOne({_id: groupId}, { groupName: 1 })
        // 判断该成员是否在群内
        let isGroup = await GroupUserModel.find({
            $and: [
                { userId: userId },
                { groupId: groupId },
                { state: { $eq: 1 } }
            ]
        })
        if (isGroup.length === 0) {
            return res.json({
                status: 202,
                data: groupNick,
                msg: '您还未加入该群哦'
            })
        }
        if (messageList.length > 0) {
            res.json({
                status: 200,
                data: {
                    groupNick,
                    messageList: messageList.reverse()
                }
            })
        } else {
            res.json({
                status: 201,
                data: groupNick,
                msg: '暂无更多'
            })
        }
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 私聊图片上传接口
 */
var storagePrivate = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./upload/private_chat")
    },
    filename: function (req, file, cb) {
        cb(null, Date.now() + "-" + file.originalname)
    }
})
var createFolder = function (folder) {
    try {
        fs.accessSync(folder)
    } catch (e) {
        fs.mkdirSync(folder)
    }
}
var uploadFolderPrivateChat = './upload/private_chat'
createFolder(uploadFolderPrivateChat)
var uploadPrivateChat = multer({ storage: storagePrivate })
// 多图片上传接口
router.post('/chat/private/photos', uploadPrivateChat.array('photos', 9), function (req, res, next) {
    let files = req.files
    let filesRes = []
    files.forEach(i => {
        filesRes.push(`/${i.filename}`)
    })
    if (files.length === 0) {
        return res.json({ res_code: 500, msg: 'error' })
    } else {
        res.json({ res_code: 200, url: filesRes })
    }
})
// 单图片上传接口
router.post('/chat/private/photo', uploadPrivateChat.single('photo'), async (req, res, next) => {
    var file = req.file
    res.json({ res_code: 200, name: file.originalname, url: `/${file.filename}` })
})

/**
 * 群聊图片上传接口
 */
var storageGroupChat = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./upload/group_chat")
    },
    filename: function (req, file, cb) {
        cb(null, Date.now() + "-" + file.originalname)
    }
})
var createFolder = function (folder) {
    try {
        fs.accessSync(folder)
    } catch (e) {
        fs.mkdirSync(folder)
    }
}
var uploadFolderGroupChat = './upload/group_chat'
createFolder(uploadFolderGroupChat)
var uploadGroupChat = multer({ storage: storageGroupChat })
// 多图片上传接口
router.post('/chat/group/photos', uploadGroupChat.array('photos', 9), function (req, res, next) {
    let files = req.files
    let filesRes = []
    files.forEach(i => {
        filesRes.push(`/${i.filename}`)
    })
    if (files.length === 0) {
        return res.json({ res_code: 500, msg: 'error' })
    } else {
        res.json({ res_code: 200, url: filesRes })
    }
})
// 单图片上传接口
router.post('/chat/group/photo', uploadGroupChat.single('photo'), async (req, res, next) => {
    var file = req.file
    res.json({ res_code: 200, name: file.originalname, url: `/${file.filename}` })
})

/**
 * 获取tabar消息页的消息列表（前提是发送过消息的好友/群）
 */
router.get('/message/list',async (req, res) => {
    const { userId } = req.query
    try {
        // 好友id列表
        let friendIdList = await FriendModel.distinct('friendId', { userId: userId, state: 1 }).populate('friendId')
        // 好友消息列表
        let friendMsgList = await UserModel.find({_id: {$in: friendIdList}}, {_id: 1, nick: 1, imgUrl: 1})
        let friendArr = JSON.parse(JSON.stringify(friendMsgList))
        const resultFriendMsgList = []
        for (let i = 0; i < friendArr.length; i++) {
            let lastMsg = await PrivateChatModel.find({$or: [{ userId, friendId: friendArr[i]._id }, { userId: friendArr[i]._id, friendId: userId }]}, {message: 1, msgType: 1, time: 1}).sort({_id: -1}).limit(1)
            if (lastMsg.length > 0) {
                Object.assign(friendArr[i], { lastMsg: lastMsg[0] })
                resultFriendMsgList.push(friendArr[i])
            }
        }
        // unreadMsgCount未读消息数
        const unreadFriendMessages = await PrivateChatModel.find({friendId: userId, state: 0}, {userId: 1, friendId: 1, state: 1})
        let arrFNum = JSON.parse(JSON.stringify(unreadFriendMessages))
        const friendCountMap = {}
        arrFNum.forEach((obj) => {
            if (obj.state === 0) {
                const id = obj.userId
                if (friendCountMap[id]) {
                    friendCountMap[id]++
                } else {
                    friendCountMap[id] = 1
                }
            }
        })
        // 给数组中的每个元素加上类型(私聊)
        for (let i = 0; i < resultFriendMsgList.length; i++) {
            Object.assign(resultFriendMsgList[i], {
                type: 'friendChat',
            })
            if (friendCountMap.hasOwnProperty(resultFriendMsgList[i]._id)) {
                Object.assign(resultFriendMsgList[i], { unreadMsgCount: friendCountMap[resultFriendMsgList[i]._id] })
            }
        }

        // 群id列表
        let groupIdList = await GroupUserModel.distinct('groupId', { userId: userId }).populate('groupId')
        // 群消息列表
        let groupMsgList = await GroupModel.aggregate([
            { $match: { _id: { $in: groupIdList } } },
            { $lookup: { from: 'group_chats', localField: '_id', foreignField: 'groupId', as: 'lastMsg' } },
            { $sort: { "lastMsg.time": -1 }},
            { $unwind: '$lastMsg' },
            { $project: { _id: 1, groupName: 1, imgUrl: 1, lastMsg: { message: 1, msgType: 1, time: 1 }} }
        ]).exec()
        let groupArr = JSON.parse(JSON.stringify(groupMsgList))
        // // 去重后的群消息列表
        const resultGroupMsgList = groupArr.reduce((acc, cur) => {
            const id1 = cur._id.replace(/[^\d\w]/g, '')  // 去除所有非字母数字的字符
            const index = acc.findIndex((item) => item._id.replace(/[^\d\w]/g, '').localeCompare(id1) === 0)
            if (index === -1) {
              acc.push(cur)
            } else {
              acc[index] = cur
            }
            return acc
        }, [])
        // 给数组中的每个元素加上类型(私聊)
        for (let i = 0; i < resultGroupMsgList.length; i++) {
            Object.assign(resultGroupMsgList[i], {
                type: 'groupChat'
            })
        }

        // 对好友、群信息按时间进行排序
        let array = [...resultFriendMsgList, ...resultGroupMsgList]
        array.sort((a, b) => {
            return -(new Date(a.lastMsg.time) - new Date(b.lastMsg.time))
        })

        res.json({
            status: 200,
            data: array
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 将好友聊天记录设置为已读（先查找与该好友是否有聊天记录，有就修改状态为已读）
 */
router.get('/message/read',async (req, res) => {
    const { userId, friendId } = req.query
    try {
        await PrivateChatModel.updateMany({ userId: friendId, friendId: userId }, { state: 1 })
        res.json({
            status: 200,
            msg: '已读'
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/** ======================================= 后台管理接口 ========================================= */
/**
 * 查询所有用户信息
 */
router.get('/getAll/user',async (req, res) => {
    const { pageNum } = req.query
    const pageSize = 8
    try {
        let userList = await UserModel.find({}, {WaiFCode: 0, token: 0, sign: 0, start: 0}).sort({_id: -1}).skip((pageNum - 1) * pageSize).limit(pageSize)
        let total = await UserModel.find().count()
        res.json({
            status: 200,
            data: {
                userList,
                total
            }
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 查询所有群
 */
router.get('/getAll/group',async (req, res) => {
    const { pageNum } = req.query
    const pageSize = 8
    try {
        let groupList = await GroupModel.find({}, {userId: 1, groupName: 1}).populate('userId', {nick: 1}).sort({_id: -1}).skip((pageNum - 1) * pageSize).limit(pageSize)
        let total = await GroupModel.find().count()
        res.json({
            status: 200,
            data: {
                groupList,
                total
            }
        })
    } catch (error) {
        res.json({
            status: 404,
            msg: '服务器错误'
        })
    }
})

/**
 * 管理员账号登录
 */
router.post('/system/login', (req, res) => {
    const { username, password } = req.body
    if (username === 'tianlovefan' && password === '123') {
        res.json({
            status: 200,
            msg: '登录成功'
        })
    } else {
        res.json({
            status: 404,
            msg: '账号或密码错误'
        })
    }
})

router.get('/test', async (req, res) => {
    try {
        let data = await UserModel.find()
        res.json({
            status: 200,
            data
        })
    } catch (error) {
        res.json({
            status: 200,
            data: 'err'
        })
    }
})

module.exports = router